//单例模式
//懒汉模式(一种高效率模式)
//不是在程序启动的时候创建实例,而是在第一次使用的时候才会创建,如果不使用了,就会节省创建实例的代价
//本质上是,能少做的就少做,直到必须要做的时候才会做
//调用时机比较分散

class SingletonLazy{
    private static volatile SingletonLazy instance = null;//避免触发优化+避免指令重排序 --> 当你有一个变量被多个线程共享时，应该考虑使用volatile
    private static Object locker = new Object();
    public static SingletonLazy getInstance() {
        //多线程连续写两个判定,结果并不是无意义的
        //多线程的这两个条件之间可能隔了很长时间或者很多指令
        //两次条件判断的结果很可能是不一样的  ---> 只是这个例子里面 两个条件的代码恰好是一样的
        //当 instance 被修改后,有些线程(在修改后启动的,就会直接跳过加锁阶段,避免了每个线程都要加锁)
        if (instance == null) {//这里判断是否要加锁  --->  实例化之前就应该要加锁
            synchronized (locker) {
                //t1 执行加锁之后,t2就会阻塞(只是其中一种情况)
                //当 t1 释放锁之后(t1 里面将 instance 成功 new 之后)
                //这样 t2 释放阻塞,进行加锁,完成 instance 的条件判断,此时 instance 就已经不是 null 了
                if (instance == null) {//这里判断是否要创建对象
                    instance = new SingletonLazy();
                }
            }
        }
            return instance;
            //什么时候调用,什么时候创建
            //不调用就不创建
            //创建一次之后,instance 就不会是 null,所以就直接返回 instance,此时就能保证实例只创建一次
    }
    private SingletonLazy(){

    }
}

public class Demo2 {
    public static void main(String[] args) {
        SingletonLazy s1 = SingletonLazy.getInstance();
        SingletonLazy s2 = SingletonLazy.getInstance();
        System.out.println(s1==s2);//输出 true
    }
}
